package buco.integrity.behaviour;

import java.util.ArrayList;
import java.util.List;

import buco.core.api.Bundle;
import buco.core.api.BundleWire;
import buco.core.api.IntegrityCheck;
import buco.core.api.IntegrityReport;

public class BehaviourIntegrityCheck extends IntegrityCheck {
	
	@Override
	public void checkIntegrity(Bundle bundle, IntegrityReport report) {
		// Check if this bundle defines behaviour protocol constraints
		List<CheckProtocol> checks = bundle.getSemanticConstraints("checkProtocol", CheckProtocol.class);
		if(checks == null) {
			return; 
		}
		
		List<BundleWire> wires = composition.getOutgoingWires(bundle, true);		
		ArrayList<DefineProtocol> availableProtocols = new ArrayList<DefineProtocol>(); 
		
		// Get available protocols
		for(BundleWire wire : wires) {
			Bundle conntectedBundle = wire.getTo(); 
			List<DefineProtocol> list = conntectedBundle.getSemanticConstraints("defineProtocol", DefineProtocol.class); 
			if(list != null) {
				availableProtocols.addAll(list); 
			}
		}
		
		// Check the protocols
		for(CheckProtocol check : checks) {
			checkProtocol(check, availableProtocols, report);
		}
	}
	
	private void checkProtocol(CheckProtocol check, List<DefineProtocol> availableProtocols, IntegrityReport report) {
		boolean foundProtocol = false; 
		
		for(DefineProtocol definition : availableProtocols) {
			if(definition.getClassName().equals(check.getClassName())) {
				foundProtocol = true; 
				if(!definition.matches(check)) { 
					report.error(String.format("Behaviour protocol violation for class %s.", check.getClassName())); 
				}
			} 
		}
		
		if(!foundProtocol) {
			report.warn(String.format("No behaviour protocol found for class %s.", check.getClassName())); 
		}
	}
}
